package com.zgc.view.controller;

import com.fx.spring.annotation.ControllerFX;
import com.fx.spring.controller.AbstractController;
import com.jfoenix.controls.JFXAlert;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXTextField;
import com.zgc.cache.CuratorClientCache;
import com.zgc.constant.ZkConstant;
import com.zgc.util.CuratorZkUtil;
import com.zgc.view.common.AlertCtrl;
import com.zgc.view.common.PopupCtrl;
import com.zgc.view.validator.FieldValidator;
import com.zgc.zkinfo.ZkNodeInfo;
import javafx.beans.binding.Bindings;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

import java.net.URL;
import java.nio.charset.Charset;
import java.util.ResourceBundle;

@ControllerFX(fxmlURL = "/view/fxml/CreateZkNode.fxml")
public class CreateZkNodeCtrl extends AbstractController<VBox> {

    @FXML
    private JFXComboBox<CreateMode> zkNodeType;
    @FXML
    private JFXComboBox<String> dataCharset;
    @FXML
    private TextArea dataTextArea;
    @FXML
    private JFXTextField parentZkPath;
    @FXML
    private JFXTextField childrenZkPath;
    @FXML
    private JFXTextField zkNodeTtl;
    @FXML
    private HBox dataInfoTop;
    @FXML
    private VBox createZkNodePae;

    @Autowired
    private PopupCtrl popupCtrl;

    private JFXAlert<String> alert;
    private final FieldValidator<JFXTextField> validator = new FieldValidator<>();


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        logger.debug("[{}]初始化完成", location);
        zkNodeType.getItems().addAll(CreateMode.values());
        zkNodeType.getSelectionModel().select(CreateMode.PERSISTENT);
        ReadOnlyObjectProperty<CreateMode> property = zkNodeType.getSelectionModel().selectedItemProperty();
        zkNodeType.promptTextProperty().bind(Bindings.createStringBinding(() -> switchCreateMode(property.getValue()), property));
        alert = initAlert();
        parentZkPath.setFocusTraversable(false);
        // 自定义校验
        childrenZkPath.setValidators(validator);
        childrenZkPath.focusedProperty().addListener((obv, ov, nv) -> {
            if (!nv) {
                validateData();
            }
        });
    }


    @FXML
    private void createNode(ActionEvent actionEvent) {
        if (validateData()) {
            CuratorFramework curatorClient = CuratorClientCache.getCuratorClient(parentZkPath.getId());
            String path;
            String parentZkPathText = parentZkPath.getText();
            if (ZkConstant.ROOT_NODE.equals(parentZkPathText)) {
                path = childrenZkPath.getText();
            } else {
                path = parentZkPathText + childrenZkPath.getText();
            }
            String data = StringUtils.isEmpty(dataTextArea.getText()) ? "" : dataTextArea.getText();
            Charset charset = Charset.forName(dataCharset.getValue());
            String createResult;
            if (dataInfoTop.getChildren().contains(zkNodeTtl)) {
                createResult = CuratorZkUtil.create(curatorClient, path, zkNodeType.getValue(), data.getBytes(charset), Long.valueOf(zkNodeTtl.getText()));
            } else {
                createResult = CuratorZkUtil.create(curatorClient, path, zkNodeType.getValue(), data.getBytes(charset));
            }
            if (createResult != null) {
                popupCtrl.enqueueRoot("节点创建成功", createResult);
                alert.close();
            } else {
                popupCtrl.enqueueRoot("节点创建失败", "");
            }
        }
    }

    /**
     * 创建和显示
     *
     * @param zkNodeInfo 连接信息
     */
    public void createAndShow(ZkNodeInfo zkNodeInfo) {
        VBox load = this.load();
        defaultInfo();
        alert.setTitle("新建节点 - " + zkNodeInfo.getCurrentPath());
        alert.setContent(load);
        parentZkPath.setId(zkNodeInfo.getId());
        parentZkPath.setText(zkNodeInfo.getPath());
        alert.show();
    }

    /**
     * 恢复默认值
     */
    private void defaultInfo() {
        alert.setTitle(null);
        parentZkPath.setId(null);
        parentZkPath.setText(null);
        childrenZkPath.setText(ZkConstant.ROOT_NODE);
        zkNodeTtl.setText(null);
        dataTextArea.clear();
        dataCharset.getSelectionModel().selectFirst();
        zkNodeType.getSelectionModel().select(CreateMode.PERSISTENT);
    }

    /**
     * 校验
     */
    private boolean validateData() {

        validator.validatorRunning(srcControl -> {
            if (StringUtils.isEmpty(childrenZkPath.getText())) {
                validator.setMessage("不能为空");
                return true;
            }

            if (!childrenZkPath.getText().startsWith("/")) {
                validator.setMessage("只能以\"/\"开头");
                return true;
            }

            if (ZkConstant.ROOT_NODE.equals(childrenZkPath.getText())) {
                validator.setMessage("路径不能只为\"/\"");
                return true;
            }
            validator.setMessage("校验通过");
            return false;
        });
        return childrenZkPath.validate();
    }


    private JFXAlert<String> initAlert() {
        JFXAlert<String> alert = new JFXAlert<>();
        alert.setSize(600, 350);
        Stage window = (Stage) alert.getDialogPane().getScene().getWindow();
        window.getIcons().add(new Image("/view/images/icon.png"));
        return alert;
    }


    private String switchCreateMode(CreateMode mode) {
        switch (mode) {
            case PERSISTENT -> {
                pushZkNodeTtl(false);
                return "持久化节点";
            }
            case PERSISTENT_SEQUENTIAL -> {
                pushZkNodeTtl(false);
                return "持久化顺序节点";
            }
            case EPHEMERAL -> {
                pushZkNodeTtl(false);
                return "临时节点";
            }
            case EPHEMERAL_SEQUENTIAL -> {
                pushZkNodeTtl(false);
                return "临时顺序节点";
            }
            case CONTAINER -> {
                pushZkNodeTtl(false);
                return "容器节点";
            }
            case PERSISTENT_WITH_TTL -> {
                pushZkNodeTtl(true);
                return "生命周期节点";
            }
            case PERSISTENT_SEQUENTIAL_WITH_TTL -> {
                pushZkNodeTtl(true);
                return "生命周期顺序节点";
            }
            default -> {
                pushZkNodeTtl(false);
                return "";
            }
        }
    }

    private void pushZkNodeTtl(boolean removeOrAdd) {
        if (removeOrAdd) {
            if (!dataInfoTop.getChildren().contains(zkNodeTtl)) {
                dataInfoTop.getChildren().add(3, zkNodeTtl);
            }
        } else {
            dataInfoTop.getChildren().remove(zkNodeTtl);
        }
    }


}
